<template>
	<div class="right_contect">
		<!-- 条件配置区域 -->
		<collapse-panel class="condition" v-if="factory" @close="handleCalculation">
			<!-- 选项卡，用于切换不同的配置面板 -->
			<el-tabs v-model="conditionActiveName" @tab-click="handleConditionClick" tab-position="left" class="tabs"
				stretch>
				<el-tab-pane label="产物配置" name="product">
					<div id="product">
						<!-- 产物配置面板 -->
						<product-panel :initial-products="factory.products" :initial-items="allItems"
							@update="handleProductsSave" />
					</div>
				</el-tab-pane>
				<el-tab-pane label="原料配置" name="ingredient">
					<div id="ingredient">
						<!-- 原料配置面板 -->
						<ingredient-panel :initial-ingredients="factory.ingredients" :initial-items="allItems"
							@update="handleIngredientsSave" />
						<p>注：原矿不需要配置</p>
					</div>
				</el-tab-pane>
				<el-tab-pane label="配方配置" name="recipe">
					<div id="recipe">
						<!-- 配方配置面板 -->
						<recipe-panel :initial-recipes="factory.recipes" @update="handleRecipesSave" />
					</div>
				</el-tab-pane>
			</el-tabs>
		</collapse-panel>
		<!-- 计算结果显示区域 -->
		<div class="result_container" v-show="factory">
			<div class="result_show" id="cytoscape"></div>
			<div class="recipe_show_container" v-show="showRecipe" :style="{
				left: tooltipPosition.x + 40 + 'px', // 偏移量根据实际情况调整
				top: tooltipPosition.y - 60 + 'px',
				zIndex: 99
			}">
				<recipe-show :recipe="showRecipeParam" />
			</div>
		</div>
	</div>
</template>

<script lang="ts">
	import Vue from "vue";
	import { mapActions, mapState } from "vuex";
	import { Factory } from '@/assets/ts/class/factory';
	import { Item } from '@/assets/ts/class/item';
	import { RecipeItem } from '@/assets/ts/class/recipeItem';
	import { storeFactory } from "@/assets/ts/factoryMethod";
	import CollapsePanel from "@/components/CollapsePanel.vue";
	import ProductPanel from "@/components/calculation/item/ProductPanel.vue";
	import IngredientPanel from "@/components/calculation/item/IngredientPanel.vue";
	import RecipePanel from "@/components/calculation/recipe/RecipePanel.vue";
	import RecipeShow from './CalRecipeShow.vue';

	import cytoscape, { Core } from 'cytoscape';
	// 改为
	const dagre = require('cytoscape-dagre'); // 绕过类型检查

	export default Vue.extend({
		name: "CalculationPanel",
		components: { CollapsePanel, IngredientPanel, ProductPanel, RecipePanel, RecipeShow },
		data() {
			return {
				conditionActiveName: "product", // 当前激活的条件配置标签
				allItems: [] as Item[], // 所有可用的物品列表

				showRecipe: false,
				showRecipeParam: null,
				tooltipPosition: { x: 0, y: 0 },
				hoverTimer: null as number | null,

				edges: [], // 结果显示的边
				nodes: [], // 结果显示的节点
				cy: null as Core | null, // 添加cytoscape实例引用
				layoutConfig: Object.freeze({
					name: 'dagre',
					zoom: 1,
					rankDir: 'LR',
					nodeSep: 80,       // 增加节点间距
					edgeSep: 100,      // 增加边间距
					spacingFactor: 1.5,
					edgeRouting: 'segments', // 优化边路由
					rankSep: 100,  // 横向层级间距复制
					fit: true,
					padding: 20,
					animate: true,
					animationDuration: 500
				}),
				edgeCountMap: new Map(),
				nodeFontSize: 20,
				edgeFontSize: 20
			};
		},
		computed: {
			// 从 Vuex 中获取 factory 状态
			...mapState({
				factory: (state : any) => state.factory, // Vuex 中的 factory 状态
			}),
		},
		methods: {
			...mapActions(['setFactoryProducts', 'setFactoryIngredients', 'setFactoryRecipes']),
			// 计算工厂的方法（暂未实现）
			calculationFatory() {
				// 计算合成路线
				alert("计算合成路线");
			},
			// 处理条件标签点击事件（暂未实现）
			handleConditionClick() {
				// 可以在这里处理标签点击事件
			},
			// 保存产物配置
			handleProductsSave(items : Item[]) {
				// 保存用户在产物配置面板中选择的物品
				console.log("保存产物：", items);
				this.setFactoryProducts(items); // 调用 Vuex 的 mutation 更新工厂产物
				storeFactory(this.factory); // 保存工厂信息到本地
			},
			// 保存原料配置
			handleIngredientsSave(items : Item[]) {
				// 保存用户在原料配置面板中选择的物品
				console.log("保存原料：", items);
				this.setFactoryIngredients(items); // 调用 Vuex 的 mutation 更新工厂原料
				storeFactory(this.factory); // 保存工厂信息到本地
			},
			//保存配方信息
			handleRecipesSave(updatedRecipes : RecipeItem[]) {
				// 直接保存整个配方列表
				console.log("保存配方：", updatedRecipes);
				this.setFactoryRecipes(updatedRecipes);
				storeFactory(this.factory);
			},
			//将该工厂信息发送至后端进行计算处理
			handleCalculation() {
				this.$api.postJson("/calculation", this.factory).then((res) => {
					if (res.code == 0) {
						this.nodes = res.data.graph.nodes;
						const edgeMap = new Map();
						const edges = res.data.graph.edges;

						edges.forEach((edge : any) => {
							const key = `${edge.data.source}~${edge.data.target}`;
							const reverseKey = `${edge.data.target}~${edge.data.source}`;
							edge.data.id = key;

							if (edgeMap.has(reverseKey)) {
								const reverseEdge = edgeMap.get(reverseKey);

								// 使用字符串类型标记
								edge.data.bidirectional = "true";
								reverseEdge.data.bidirectional = "true";

								edgeMap.delete(reverseKey);
							} else {
								edgeMap.set(key, edge);
							}
						});

						// 处理未配对边
						edgeMap.forEach(edge => {
							edge.data.bidirectional = "false";
						});


						this.edges = edges;
						console.log(this.nodes.map((node)=>{
							return {
								...node.data
							};
						}));
						console.log(this.edges.map((e)=>{
							return {
								...e.data
							};
						}));
						this.updateCytoscape();
					}
					else {
						this.$message.error(res.message);
					}
				});
			},
			// 封装cytoscape更新逻辑
			updateCytoscape() {
				console.log("更新Cytoscape");
				if (!this.cy) return;
				// 1. 清除现有元素
				this.cy.elements().remove();
				// 2. 批量添加新元素（性能优化）
				this.cy.batch(() => {
					this.cy!.add([...this.nodes, ...this.edges]);
				});
				// 3. 应用布局并自适应视图
				this.cy.layout(this.layoutConfig).run();
				// 4. 自适应缩放
				this.cy.fit(undefined, 20); // 添加20px的边距
				// 5. 添加交互提示（可选）
				this.cy.on('mouseover', 'node', (event) => {
					event.target.addClass('highlight');
				});
				this.cy.on('mouseout', 'node', (event) => {
					event.target.removeClass('highlight');
				});
			},
			// 新增方法
			handleNodeInteraction(event : cytoscape.EventObjectNode) {
				const node = event.target;
				if (node.data("type") != 0) return;
				const pos = node.renderedPosition();
				const container = document.getElementById('cytoscape')!;

				// 转换为页面坐标
				const rect = container.getBoundingClientRect();
				this.tooltipPosition = {
					x: pos.x + rect.left + window.scrollX,
					y: pos.y + rect.top + window.scrollY
				};
				var idStr : string = node.data('id');
				if (idStr == "" || idStr == null) return;
				var id = idStr.substring(2);
				if (id == null || id == undefined || id == "") return null;
				this.$api.get("/recipe/get/" + id).then((res) => {
					this.showRecipeParam = res.data.recipe;
					this.showRecipe = true;
				});
			},
			initCytoscape() {
				// 初始化cytoscape实例
				cytoscape.use(dagre);
				const container = document.getElementById("cytoscape");
				if (!container) return;
				// 1. 定义严格的类型枚举
				type NodeType = 0 | 1 | 2 | 3;

				// 2. 定义类型化的颜色配置
				const nodeTypeColors : Record<NodeType, { bg : string; border : string }> = {
					0: { bg: '#E3F2FD', border: '#2196F3' },
					1: { bg: '#E8F5E9', border: '#4CAF50' },
					2: { bg: '#FFF3E0', border: '#FF9800' },
					3: { bg: '#F3E5F5', border: '#9C27B0' }
				};
				// 保存实例引用
				var cy = cytoscape({
					container: container,
					elements: [], // 初始为空，通过updateCytoscape填充
					layout: this.layoutConfig,
					wheelSensitivity: 0.4,
					style: [
						{
							selector: 'node',
							style: {
								'shape': 'round-rectangle', // 圆角矩形
								'width': 160,
								'height': 60,
								'label': "data(label)",
								'border-width': 2,
								'padding': '10px',
								'text-valign': 'center',
								'text-halign': 'center',
								'font-size': this.nodeFontSize,
								'color': '#37474F',
								'text-wrap': 'wrap',
								'text-max-width': '140px',
								// 动态样式
								'background-color': (ele : cytoscape.NodeSingular) => {
									const type = ele.data('type') as NodeType; // 类型断言
									return nodeTypeColors[type]?.bg || nodeTypeColors[0].bg; // 安全访问
								},
								'border-color': (ele : cytoscape.NodeSingular) => {
									const type = ele.data('type') as NodeType;
									return nodeTypeColors[type]?.border || nodeTypeColors[0].border;
								},
							}
						},
						// 边样式
						{
							selector: 'edge',
							style: {
								'width': 2,
								'line-color': '#B0BEC5',
								'target-arrow-shape': 'triangle',
								'target-arrow-color': '#90A4AE',
								'curve-style': 'straight', // 默认直线

								// 标签样式优化
								'label': 'data(label)',
								'text-rotation': 'autorotate',
								'text-margin-y': -10,
								'font-size': this.edgeFontSize,
								'color': '#607D8B',
								'text-outline-color': '#FFF',
								'text-outline-width': 1,
							}
						},

						// 双向边特殊样式
						{
							selector: 'edge[bidirectional="true"]',
							style: {
								'curve-style': 'unbundled-bezier',
								'control-point-distance': 60,  // 正负控制点实现对称曲线
								'control-point-weight': 0.4,
								'edge-distances': 'intersection' // 自动避让
							}
						},
						// 高亮状态
						{
							selector: '.highlight',
							style: {
								'border-width': 3,
								'z-index': 9999,
								'target-arrow-color': '#FF5722',
							}
						}
					]
				});
				// 点击事件
				cy.on('tap', 'node', (event) => {
					event.target.animate({
						style: {
							'border-width': 8,
							'border-opacity': 0.5
						}
					}, {
						duration: 300,
						complete: () => event.target.style('border-width', 2)
					});
					this.handleNodeInteraction(event);
				});
				cy.on('mouseover', 'node', (event) => {
					event.target.animate({
						style: {
							width: 170,
							height: 65,
							'font-size': this.nodeFontSize + 1
						}
					}, { duration: 200 });
					this.hoverTimer = setTimeout(() => {
						this.handleNodeInteraction(event);
					}, 1000);
				});

				cy.on('mouseout', 'node', (event) => {
					event.target.animate({
						style: {
							width: 160,
							height: 60,
							'font-size': this.nodeFontSize,
						}
					}, { duration: 200 });
					if (this.hoverTimer) {
						clearTimeout(this.hoverTimer);
						this.hoverTimer = null;
					}
					this.showRecipe = false;
				});

				cy.on('mouseover', 'edge', (evt) => {
					evt.target.animate({
						style: {
							'text-outline-width': 2,
							'color': '#ff0000',
							'line-color': '#ff0000',
							'font-size': this.edgeFontSize + 1,
							'z-index': 99999,
						}
					}, { duration: 200 });
				});

				cy.on('mouseout', 'edge', (evt) => {
					evt.target.animate({
						style: {
							'text-outline-width': 1,
							'color': '#607D8B',
							'line-color': '#B0BEC5',
							'font-size': this.edgeFontSize,
							'z-index': 1,
						}
					}, { duration: 200 });
				});

				this.cy = Object.freeze(cy);
			}
		},
		mounted() {
			// 组件挂载后加载工厂信息和所有物品列表
			console.log("工厂信息：", this.factory);
			this.$api.get("/item/list/use").then((res : any) => {
				this.allItems = res.data.list; // 加载所有可用的物品
			});
			this.$nextTick(() => {
				this.initCytoscape();
			});
		},
		// 组件销毁时清理
		beforeDestroy() {
			if (this.cy) {
				this.cy.destroy(); // 避免内存泄漏
				this.cy = null;
			}
		}
	});
</script>

<style lang="less" scoped>
	.right_contect {
		width: 100%; // 右侧内容区域宽度
		max-height: calc(100vh - 60px); // 最大高度
		overflow: auto; // 溢出时显示滚动条

		.condition {
			width: calc(100% - 302px);

			.tabs {

				// 选项卡样式
				/deep/.el-tabs__item.is-left {
					height: 60px; // 选项卡高度
					line-height: 60px; // 行高
					font-size: 16px; // 字体大小
				}

				.recipe {
					max-height: 600px;
				}
			}
		}

		.result_container {
			width: 100%; // 计算结果显示区域宽度
			height: calc(100vh - 100px); // 高度

			.result_show {
				width: 90%; // 显示区域宽度
				margin: auto; // 水平居中
				margin-top: 30px; // 顶部外边距
				height: 98%; // 高度
				background-color: white; // 背景颜色
				border-radius: 10px; // 圆角
				border: 1px solid #DCDFE6; // 边框样式
			}

			.recipe_show_container {
				position: absolute;
				background-color: white;
				border-radius: 8px;
				width: 400px;
				height: 100px;
				z-index: 9;
			}
		}
	}
</style>